home *** CD-ROM | disk | FTP | other *** search
/ Skunkware 5 / Skunkware 5.iso / src / Tools / glimpse-2.1 / index / build_in.c next >
C/C++ Source or Header  |  1995-06-21  |  49KB  |  1,469 lines

  1. /* Copyright (c) 1994 Sun Wu, Udi Manber, Burra Gopal.  All Rights Reserved. */
  2. /* ./glimpse/index/build_in.c */
  3.  
  4. /* --------------------------------------------------------------
  5.     build_index():  build an index list from a set of files.
  6.     INPUT: a set of file names
  7.        char *name_list[MAX_LIST];
  8.        a partition table
  9.        in p_table[MAX_PARTITION];
  10.     OUTPUT: an index list;
  11.        char *index_list;
  12.        the index list is a char string as follows:
  13.        each entry of the index list contains two parts:
  14.        name and indices, where name is an ascii character string,
  15.            and indices is a list of short integer. (unsigned char)
  16.            We use newline as a 'record delimiter' (a 'record is logically
  17.        a word associated with its indices), and WORD_END_MARK to separate
  18.        a word from its list of indices (s.t. fscanf %s works).
  19.        Since we restrict the max number of partitions to be 255.
  20.        a byte is enough to represent the index value. Note that there
  21.        cannot be a partition #ed '\n'.
  22.        An example index list: (in logical view)
  23.            this 12 19 \n is 9 17 12 18 19 \n an 7 12 \n example 16 \n
  24. -----------------------------------------------------------------------*/
  25.  
  26. #include <stdlib.h>
  27. #include "glimpse.h"
  28.  
  29. #define debugt
  30. #define BINARY 1
  31. /* #define SW_DEBUG  the original sw output of index set */
  32.  
  33. /* This flag must always be defined: it is used only in build_in.c */
  34. /* #define UDI_DEBUG  the original outputs of each indexed file */
  35.  
  36. /* Some variables used throughout */
  37. #if    BG_DEBUG
  38. FILE  *LOGFILE;     /* file descriptor for LOG output */
  39. #endif    /*BG_DEBUG*/
  40. FILE  *STATFILE;    /* file descriptor for statistical data about indexed files */
  41. FILE  *MESSAGEFILE;    /* file descriptor for important messages meant for the user */
  42. char  INDEX_DIR[MAX_LINE_LEN];
  43. struct stat istbuf;
  44. struct stat excstbuf;
  45. struct stat incstbuf;
  46.  
  47. int ICurrentFileOffset;
  48. int NextICurrentFileOffset;
  49.  
  50. /* Some options used throughout */
  51. int OneFilePerBlock = OFF;
  52. extern int IndexNumber;
  53. extern int CountWords;
  54. extern int StructuredIndex;
  55. extern int InterpretSpecial;
  56. int total_size = 0;
  57. int MAXWORDSPERFILE = 0;
  58. int NUMERICWORDPERCENT = 50;
  59. int AddToIndex = OFF;
  60. int FastIndex = OFF;
  61. int BuildDictionary = OFF;
  62. int BuildDictionaryExisting = OFF;
  63. int CompressAfterBuild = OFF;
  64. int IncludeHigherPriority = OFF;
  65. int FilenamesOnStdin = OFF;
  66. int UseFilters = OFF;
  67. int ByteLevelIndex = OFF;
  68. /* int IndexUnderscore = OFF; */
  69. int IndexableFile = OFF;
  70. int MAX_INDEX_PERCENT = DEF_MAX_INDEX_PERCENT;
  71. int MAX_PER_MB = DEF_MAX_PER_MB;
  72.  
  73. int AddedMaxWordsMessage = OFF;
  74. int AddedMixedWordsMessage = OFF;
  75.  
  76. int  icount=0; /* count the number of my_malloc for indices structure */
  77. int  hash_icount=0; /* to see how much was added to the current hash table */
  78. int  save_icount=0; /* to see how much was added to the index by the current file */
  79. int  numeric_icount=0; /* to see how many numeric words were there in the current file */
  80.  
  81. int num_filter=0;
  82. int filter_len[MAX_FILTER];
  83. CHAR *filter[MAX_FILTER];
  84. CHAR *filter_command[MAX_FILTER];
  85.  
  86. int mask_int[32] = MASK_INT;
  87.  
  88. char *name_list[MAX_LIST];
  89. int disable_list[FILEMASK_SIZE];
  90. int  p_table[MAX_PARTITION];
  91. int *size_list = NULL;    /* temporary area to store size of each file */
  92. int  p_size_list[MAX_PARTITION];    /* sum of the sizes of the files in each partition */
  93. int part_num = 1;   /* number of partitions */
  94.  
  95. int memory_usage = 0;
  96.  
  97. extern char *getword();
  98. int file_num = 0;
  99. extern int attr_num;
  100.  
  101. char *
  102. my_malloc(len)
  103.     int len;
  104. {
  105.     char *s;
  106. /*    char *malloc(); declared in stdlib.h */
  107.  
  108.     if ((s = (char *)malloc(len)) != NULL) memory_usage += len;
  109.     else fprintf(stderr, "malloc failed after memory_usage = %x Bytes\n", memory_usage);
  110.     /* Don't exit since might do traverse here: exit in glimpse though */
  111. #if    BG_DEBUG
  112.     printf("m:%x ", memory_usage);
  113. #endif    /*BG_DEBUG*/
  114.     return s;
  115. }
  116.  
  117. my_free(ptr, size)
  118.     void *ptr;
  119.     int size;
  120. {
  121.     free(ptr);
  122.     memory_usage -= size;
  123. #if    BG_DEBUG
  124.     printf("f:%x ", memory_usage);
  125. #endif    /*BG_DEBUG*/
  126. }
  127.  
  128. int  bp=0;                          /* buffer pointer */
  129. unsigned char word[MAX_WORD_BUF];
  130. int FirstTraverse1 = ON;
  131.  
  132. struct  indices *ip;
  133.  
  134. struct token *hash_table[MAX_64K_HASH+1];
  135.  
  136. build_index()
  137. {
  138.     if (AddToIndex || FastIndex) {
  139.         FirstTraverse1 = OFF;
  140.     }
  141.         build_hash();
  142.         traverse1();
  143.         return;
  144. }
  145.  
  146. /* ----------------------------------------------------------------------
  147. traverse()
  148. function: traverse the hash list of indices = a hash list is a array of
  149. linked list, where every node in a linked list contains a word whose
  150. hash_value is the same.
  151. While traversing the hash list, traverse() output a stream of index list.
  152. It also my_frees the memory used in hash_table.
  153. ------------------------------------------------------------------------*/
  154. traverse()
  155. {
  156.     int numseencount = 0;
  157.     int numelements;
  158.     int numonline;
  159.     int  i, j, k;
  160.     struct token *tp, *tp_old;
  161.     struct indices *ip, *ip_old;
  162.     FILE   *f_out;
  163.     char   s[256];
  164.     char   *word;
  165.     int    x = -1, y=0, diff, temp, even_words=1;    /* 0 is an even number */
  166.  
  167. #ifdef    SW_DEBUG
  168.     printf("in traverse()\n");
  169. #endif
  170.     sprintf(s, "%s/%s", INDEX_DIR, I2);
  171.     if ((f_out = fopen(s, "w")) == NULL) {
  172.     fprintf(stderr, "Cannot open %s for writing\n", s);
  173.     exit(3);
  174.     }
  175.     for(i=0; i<MAX_64K_HASH; i++) {
  176.         if(hash_table[i] == NULL) continue;
  177.         tp = hash_table[i];
  178.         tp_old = tp;
  179.         while(tp != NULL) {   /* traverse the token list */
  180.         if (StructuredIndex) {  /* force big-endian as usual */
  181.         k = encode32b(tp->attribute);
  182.         putc((k&0xff000000)>>24, f_out);
  183.         putc((k&0x00ff0000)>>16, f_out);
  184.         putc((k&0x0000ff00)>>8, f_out);
  185.         putc((k&0x000000ff), f_out);
  186.         }
  187.         word = tp->word;
  188.             while(*word != '\0') {  /* copy the word to output */
  189.         putc(*word++, f_out);
  190.             }
  191.  
  192.         /* Look for stop lists */
  193.         if (OneFilePerBlock && !ByteLevelIndex && (file_num > MaxNum8bPartition) && (tp->totalcount > (file_num * MAX_INDEX_PERCENT / 100))) {
  194.         putc(ALL_INDEX_MARK, f_out);
  195.         putc(DONT_CONFUSE_SORT, f_out);
  196.         goto next_token;
  197.         }
  198.         else if (ByteLevelIndex && (tp->totalcount > ( (((total_size>>20) > 0) && ((total_size>>20)*MAX_PER_MB < MAX_ALL_INDEX)) ? ((total_size>>20) * MAX_PER_MB) : DEF_ALL_INDEX) )) {
  199.         putc(ALL_INDEX_MARK, f_out);
  200.         putc(DONT_CONFUSE_SORT, f_out);
  201.         goto next_token;
  202.         }
  203.  
  204.         putc(WORD_END_MARK, f_out);
  205.         numonline = 0;
  206.         x = -1;
  207.         y = 0;
  208.         even_words = 1;
  209.  
  210.         ip = tp->ip;    /* traverse the indices list */
  211.             ip_old = ip;
  212.         numelements = 0;
  213.             while(ip != NULL) {
  214.         numelements ++;
  215.         if (CountWords) {
  216.             fprintf(f_out, "%d", ip->count);
  217.         }
  218.         else {
  219.             if (ByteLevelIndex) {
  220.             for (j=0; j<ip->count; j++) {
  221.                 if ((ip->offset[j] <= y) && (y > 0) && (x == ip->index[j])) {    /* consecutive offsets not increasing in same file! */
  222.                 fprintf(stderr, "ignoring (%d, %d) > (%d, %d)\n", x, y, ip->index[j], ip->offset[j]);
  223.                 continue;    /* error! */
  224.                 }
  225.                 if (numonline >= MAX_PER_LINE) {
  226.                 /* terminate current line since it is too late to put ALL_INDEX_MARK now ... Unfortunate since sort is screwedup */
  227.                 putc('\n', f_out);
  228. #if    0
  229.                 putc('\n', stdout);
  230. #endif    /*0*/
  231.  
  232.                 if (StructuredIndex) {  /* force big-endian as usual */
  233.                     k = encode32b(tp->attribute);
  234.                     putc((k&0xff000000)>>24, f_out);
  235.                     putc((k&0x00ff0000)>>16, f_out);
  236.                     putc((k&0x0000ff00)>>8, f_out);
  237.                     putc((k&0x000000ff), f_out);
  238.                 }
  239.                 word = tp->word;
  240.                 while(*word != '\0') {  /* copy the word to output */
  241.                     putc(*word++, f_out);
  242.                 }
  243.                 putc(WORD_END_MARK, f_out);
  244.                 numonline = 0;
  245.                 x = -1;    /* to force code below to output it as if it is a fresh file */
  246.                 y = 0;    /* must output first offset as is, rather than difference */
  247.                 }
  248.  
  249.                 if (x != ip->index[j]) {
  250.                 if (x != -1) {
  251.                     temp = encode8b(0);
  252.                     putc(temp, f_out);    /* can never ordinarily happen since ICurrentFileOffset is always ++d => delimiter */
  253.                 }
  254.                 if (file_num <= MaxNum8bPartition) {
  255.                     x = encode8b(ip->index[j]);
  256.                     putc(x&0x000000ff, f_out);
  257.                 }
  258.                 else {
  259.                     x = encode16b(ip->index[j]);
  260.                     putc((x&0x0000ff00)>>8, f_out);
  261.                     putc(x&0x000000ff, f_out);
  262.                 }
  263.                 x = ip->index[j];    /* for next round */
  264. #if    0
  265.                 printf("#######x=%d ", x);
  266. #endif    /*0*/
  267.                 y = 0;
  268.                 }
  269.  
  270.                 diff = ip->offset[j] - y;
  271.                 y = ip->offset[j];
  272.                 if (diff < MaxNum1BPartition) {
  273.                 temp = encode8b(diff);
  274.                 putc(temp, f_out);
  275.                 }
  276.                 else if (diff < MaxNum2BPartition) {
  277.                 temp = encode8b((diff/MaxNum8bPartition) | 0x40);
  278.                 putc(temp, f_out);
  279.                 temp = encode8b(diff % MaxNum8bPartition);
  280.                 putc(temp, f_out);
  281.                 }
  282.                 else if (diff < MaxNum3BPartition) {
  283.                 temp = encode8b((diff/MaxNum16bPartition) | 0x80);
  284.                 putc(temp, f_out);
  285.                 temp = encode16b(diff % MaxNum16bPartition);
  286.                 putc((temp & 0x0000ff00) >> 8, f_out);
  287.                 putc(temp & 0x000000ff, f_out);
  288.                 }
  289.                 else {
  290.                 temp = encode8b((diff/MaxNum24bPartition) | 0xc0);
  291.                 putc(temp, f_out);
  292.                 temp = encode24b(diff % MaxNum24bPartition);
  293.                 putc((temp & 0x00ff0000) >> 16, f_out);
  294.                 putc((temp & 0x0000ff00) >> 8, f_out);
  295.                 putc(temp & 0x000000ff, f_out);
  296.                 }
  297.                 numonline ++;
  298.             }
  299.             } /* ByteLevelIndex */
  300.             else if (OneFilePerBlock) {
  301.             if (file_num <= MaxNum8bPartition) {
  302.                 for(j=0; j<ip->count; j++) {
  303.                 putc(encode8b(ip->index[j]), f_out);
  304.                 }
  305.             }
  306.             else if (file_num <= MaxNum12bPartition) {
  307.               for(j=0; j<ip->count; j++) {
  308.                 x = encode12b(ip->index[j]);
  309.                 if (even_words) {
  310.                 putc(x & 0x000000ff, f_out);    /* lsb */
  311.                 y = (x & 0x00000f00)>>8;    /* msb */
  312.                 even_words = 0;
  313.                 }
  314.                 else {    /* odd number of words so far */
  315.                     y |= (x&0x00000f00)>>4; /* msb of x into msb of y */
  316.                 putc(y, f_out);
  317.                 putc(x&0x000000ff, f_out);
  318.                 even_words = 1;
  319.                 }
  320.               }
  321.             }
  322.             else if (file_num <= MaxNum16bPartition) {
  323.                 for(j=0; j<ip->count; j++) {
  324.                 x = encode16b(ip->index[j]);
  325.                 putc((x&0x0000ff00)>>8, f_out);
  326.                 putc(x&0x000000ff, f_out);
  327.                 }
  328.             }
  329.             } /* OneFilePerBlock */
  330.             else {    /* normal partitions */
  331.             for(j=0; j<ip->count; j++) {
  332.                 putc(ip->index[j], f_out);
  333.             }
  334.             }
  335.         }
  336.                 ip = ip->next_i;   /* go to next indices */
  337.                 my_free(ip_old, sizeof(struct indices));
  338.                 ip_old = ip;
  339.             }
  340.         if (!ByteLevelIndex && OneFilePerBlock && !even_words && (file_num <= MaxNum12bPartition))
  341.         putc(y, f_out);
  342.  
  343. next_token:
  344.         if (putc('\n', f_out) == EOF) {
  345.         fprintf(stderr, "Error: write failed at %s:%d\n", __FILE__, __LINE__); 
  346.         exit(2);
  347.         }
  348.             tp = tp->next_t;    /* go to next token */
  349. #if    0
  350.         fprintf(stderr, "numelements=%d\n", numelements);
  351. #endif    /*0*/
  352. #if    BG_DEBUG
  353.         memory_usage -= (strlen(tp_old->word) + 1);
  354. #endif    /*BG_DEBUG*/
  355.         my_free(tp_old->word, 0);
  356.             my_free(tp_old, sizeof(struct token));
  357.             tp_old = tp;
  358.         numseencount ++;
  359.         }
  360.  
  361.     }
  362. #if    BG_DEBUG
  363.     fprintf(stderr, "out of traverse(): saved/freed %d tokens: new usage: %d\n", numseencount, memory_usage);
  364. #endif
  365.     fflush(f_out);
  366.     fclose(f_out);
  367. }
  368.  
  369. traverse1()
  370. {
  371.     FILE *i1, *i2, *i3;
  372.     int ret;
  373.     char s[256];
  374.     char s1[MAX_LINE_LEN];
  375.     extern int errno;
  376.     static int maxsortlinelen = 0;
  377.  
  378.     if (maxsortlinelen <= 0) {
  379.     if (file_num < MaxNum8bPartition)
  380.         maxsortlinelen = round((MaxNum8bPartition * sizeof(int) + MAX_NAME_SIZE), MAX_LINE_LEN) * MAX_LINE_LEN;
  381.     else if (file_num < MaxNum12bPartition)
  382.         maxsortlinelen = round((MaxNum12bPartition * sizeof(int) + MAX_NAME_SIZE), MAX_LINE_LEN) * MAX_LINE_LEN;
  383.     else maxsortlinelen = MAX_SORTLINE_LEN;
  384.     }
  385.  
  386.     traverse();    /* will produce .i2 and my_free allocated memory */
  387. #if    USESORTZOPTION
  388.     sprintf(s, "sort -z %d %s/%s > %s/%s\n", maxsortlinelen, INDEX_DIR, I2, INDEX_DIR, O2);
  389. #else    /*USESORTZOPTION*/
  390.     sprintf(s, "sort %s/%s > %s/%s\n", INDEX_DIR, I2, INDEX_DIR, O2);
  391. #endif    /*USESORTZOPTION*/
  392.  
  393. #ifdef SW_DEBUG
  394.     printf("%s", s);
  395. #endif
  396.     if((ret=system(s)) != 0) {
  397.     sprintf(s1, "system('%s') failed at:\n\t File=%s, Line=%d, Errno=%d", s, __FILE__, __LINE__, errno);
  398.     perror(s1);
  399.     fprintf(stderr, "Please run the program again (if there's no memory try increasing the swap area)\n");
  400.     exit(1);
  401.     }
  402.  
  403. #ifdef SW_DEBUG
  404.     printf("mv .o2 .i2\n"); fflush(stdout);
  405. #endif
  406.     sprintf(s, "mv %s/%s %s/%s\n", INDEX_DIR, O2, INDEX_DIR, I2);
  407.     system(s);
  408. #if    0
  409.     printf("traversed\n");
  410.     sprintf(s, "head -10 %s/%s\n", INDEX_DIR, I2);
  411.     system(s);
  412. #endif    /*0*/
  413.  
  414.     /*
  415.      * This flag is set from outside iff build-fast | build-addto option is set.
  416.      */
  417.     if(FirstTraverse1) {
  418.     /* Mention whether numbers are indexed */
  419.     if(IndexNumber) sprintf(s, "echo %%1234567890 > %s/%s\n", INDEX_DIR, INDEX_FILE);
  420.     else sprintf(s, "echo %% > %s/%s\n", INDEX_DIR, INDEX_FILE);
  421.     system(s);
  422.  
  423.     /* Put the magic number: 0 if not 1file/blk, numfiles otherwise */
  424.     if (OneFilePerBlock) {
  425.         if (ByteLevelIndex) sprintf(s, "echo %%-%d >> %s/%s\n", file_num, INDEX_DIR, INDEX_FILE);
  426.         else sprintf(s, "echo %%%d >> %s/%s\n", file_num, INDEX_DIR, INDEX_FILE);
  427.     }
  428.     else sprintf(s, "echo %%0 >> %s/%s\n", INDEX_DIR, INDEX_FILE);
  429.     system(s);
  430.  
  431.     /* Put the magic number: 0 if not structured index, 1 if so */
  432.     if (StructuredIndex) sprintf(s, "echo %%%d >> %s/%s\n", attr_num, INDEX_DIR, INDEX_FILE);
  433.     else sprintf(s, "echo %%0 >> %s/%s\n", INDEX_DIR, INDEX_FILE);
  434.     system(s);
  435.  
  436. #ifdef    SW_DEBUG
  437.     sprintf(s, "ls -l %s/.glimpse*\n", INDEX_DIR);
  438.     system(s);
  439. #endif
  440.         sprintf(s, "cat %s/%s >> %s/%s\n", INDEX_DIR, I2, INDEX_DIR, INDEX_FILE);
  441.         system(s);
  442.     sprintf(s, "rm %s/%s\n", INDEX_DIR, I2);
  443.     system(s);
  444. #ifdef    SW_DEBUG
  445.     sprintf(s, "ls -l %s/.glimpse*\n", INDEX_DIR);
  446.     system(s);
  447. #endif
  448. #if    0
  449.     printf("catted\n");
  450.     sprintf(s, "head -10 %s/%s\n", INDEX_DIR, INDEX_FILE);
  451.     system(s);
  452. #endif    /*0*/
  453.         FirstTraverse1 = 0;
  454.         return;
  455.     }
  456.     /* else not first-traverse */
  457.  
  458.     sprintf(s, "%s/%s", INDEX_DIR, INDEX_FILE);
  459.     if((i1 = fopen(s, "r")) == 0) {    /* new stuff */
  460.         fprintf(stderr, "can't open %s for reading\n", s);
  461.         exit(2);
  462.     }
  463.     sprintf(s, "%s/%s", INDEX_DIR, I2);
  464.     if((i2 = fopen(s, "r")) == 0) {    /* old stuff */
  465.         fprintf(stderr, "can't open %s for reading\n", s);
  466.         exit(2);
  467.     }
  468.     sprintf(s, "%s/%s", INDEX_DIR, I3);
  469.     if((i3 = fopen(s, "w")) == 0) {    /* result */
  470.         fprintf(stderr, "can't open %s for writing\n", s);
  471.         exit(2);
  472.     }
  473.  
  474.     /* Copy the 3 option fields (indexnumber, onefileperblock, structuredqueries) */
  475.     fgets(s, 256, i1);
  476.     s[255] = '\0';
  477.     fputs(s, i3);
  478.     fgets(s, 256, i1);
  479.     s[255] = '\0';
  480.     fputs(s, i3);
  481.     fgets(s, 256, i1);
  482.     s[255] = '\0';
  483.     fputs(s, i3);
  484.  
  485.     merge_in(i2, i1, i3);
  486.     /* merge_in(i1, i2, i3); */
  487. #ifdef    BG_DEBUG
  488.     fprintf(stderr, "out of merge_in()\n");
  489. #endif    /*BG_DEBUG*/
  490.     fclose(i1);
  491.     fclose(i2);
  492.     fclose(i3);
  493. #ifdef SW_DEBUG
  494.     printf("mv .i3 %s\n", INDEX_FILE); fflush(stdout);
  495. #endif
  496.     sprintf(s, "mv %s/%s %s/%s", INDEX_DIR, I3, INDEX_DIR, INDEX_FILE);
  497.     system(s);
  498. #ifdef SW_DEBUG
  499.     printf("ls -l .i2 %s\n", INDEX_FILE); fflush(stdout);
  500.     sprintf(s, "ls -l %s/.glimpse*", INDEX_DIR);
  501.     printf("%d\n", system(s));
  502. #endif
  503. #if    0
  504.     printf("merged\n");
  505.     sprintf(s, "head -10 %s/%s\n", INDEX_DIR, INDEX_FILE);
  506.     system(s);
  507. #endif    /*0*/
  508. }
  509.  
  510. /* --------------------------------------------------------------------
  511. build_hash():
  512. input: a set of filenames in name_list[], a partition table p_table[]
  513. output: a hash table hash_table[].
  514. -----------------------------------------------------------------------*/
  515. build_hash()
  516. {
  517.     FILE *fd;                          /* opened file number */
  518.     int  i, pn;                  /* pn: current partition */
  519.     int  num_read;
  520.     char word[256];
  521.     struct stat stbuf;
  522.     int offset;
  523.     int toread;
  524.     unsigned char *buffer;
  525.     unsigned char *bx;
  526.     unsigned char *buffer_end;
  527.     int tried_once = 0;
  528.     int attribute;
  529.     int ret;
  530.     char outname[MAX_LINE_LEN];
  531.     char *unlinkname = NULL;
  532.     int pid = getpid();
  533.  
  534.     if (StructuredIndex) region_initialize();
  535.     init_hash_table();
  536. #ifdef debug
  537.     printf("entering build_hash(), part_num=%d\n", part_num);
  538. #endif
  539.  
  540.     tried_once = 0;
  541. try_again_1:
  542.     buffer = (unsigned char *) my_malloc(sizeof(char)* BLOCK_SIZE + 10);    /* always read in units of BLOCK_SIZE or less */
  543.     if(buffer == NULL) {
  544.     fprintf(stderr, "not enough memory in build_hash\n");
  545.     if (tried_once) return;
  546.     traverse1();
  547.     init_hash_table();
  548.     tried_once = 1;
  549.     goto try_again_1;
  550.     }
  551.     bx = buffer;
  552.  
  553.     if (OneFilePerBlock) {
  554.     for(i=0; i<file_num; i++) {
  555.         unlinkname = NULL;
  556.         if (disable_list[block2index(i)] & mask_int[i%(8*sizeof(int))]) continue;
  557.         if ((ret = tuncompress_file(name_list[i], outname, TC_EASYSEARCH | TC_OVERWRITE | TC_NOPROMPT)) > 0) {    /* do not remove old .TZ file */
  558.         if (((fd = fopen(outname, "r")) == NULL) ) {
  559.             remove_filename(i, -1);
  560.             unlink(outname);
  561.             continue;
  562.         }
  563.         /* not handling structured indices for compressed files now since offset computations will be incorrect */
  564.         unlinkname = outname;
  565.         goto index_file1;
  566.         }
  567.  
  568.         /* Try to apply the filter */
  569.         sprintf(outname, "%s/.glimpse_apply.%d", INDEX_DIR, pid);
  570.         if ((ret = apply_filter(name_list[i], outname)) == 1) {
  571.         /* Some pattern matched AND some filter was successful */
  572.         if (((fd = fopen(outname, "r")) == NULL) ) {    /* error: shouldn't have returned 1! */
  573.             remove_filename(i, -1);
  574.             unlink(outname);
  575.             continue;
  576.         }
  577.         /* not handling structured indices for filtered files now since offset computations will be incorrect */
  578.         unlinkname = outname;
  579.         goto index_file1;
  580.         }
  581.         else if (ret == 2) {
  582.         /* Some pattern matched but no filter was successful */
  583.         if (filetype(name_list[i], 0)) {    /* try to index input file if it satisfies filetype */
  584.             remove_filename(i, -1);
  585.             unlink(outname);
  586.             continue;
  587.         }
  588.         unlinkname = outname;
  589.         }
  590.  
  591.         if (StructuredIndex && (-1 == region_create(name_list[i]))) {
  592.         fprintf(stderr, "permission denied or non-existent file: %s\n", name_list[i]);
  593.         remove_filename(i, -1);
  594.         continue;
  595.         }
  596.             if (((fd = fopen(name_list[i], "r")) == NULL) ) {
  597.         fprintf(stderr, "permission denied or non-existent file: %s\n", name_list[i]);
  598.         remove_filename(i, -1);
  599.         if (StructuredIndex) region_destroy();    /* cannot happen! */
  600.         continue;
  601.             }
  602.  
  603.     index_file1:
  604. #ifdef SW_DEBUG
  605.         if (AddToIndex || FastIndex) printf("adding words of %s in %d\n", name_list[i], i);
  606.         printf("%s\n", name_list[i]);
  607. #endif
  608.         /* stat(name_list[i], &stbuf); Chris Dalton */
  609.         fstat(fileno(fd), &stbuf);
  610. #ifdef    SW_DEBUG
  611.         printf("filesize: %d\n", stbuf.st_size);
  612. #endif
  613.  
  614. #ifdef    UDI_DEBUG
  615.         printf("%s  ", name_list[i]);
  616.         printf("size: %d  ", stbuf.st_size);
  617. #endif
  618.  
  619.         /* buffer always points to a BLOCK_SIZE block of allocated memory */
  620.         for (offset = 0; offset < stbuf.st_size; offset += BLOCK_SIZE) {
  621.         NextICurrentFileOffset = ICurrentFileOffset = offset;
  622.         toread = offset + BLOCK_SIZE >= stbuf.st_size ? stbuf.st_size - offset : BLOCK_SIZE;
  623.         fseek(fd, offset, 0);
  624.  
  625.         bx= buffer;
  626.         num_read = 0;
  627.         while ((toread > 0) && ((num_read = fread(bx, 1, toread, fd)) < toread)) {
  628.             if (num_read <= 0) {
  629.             buffer = bx;
  630.             fprintf(stderr, "read error on file %s at offset %d\n", name_list[i], offset);
  631.             goto break_break1;    /* C doesn't have break; break; */
  632.             }
  633.             bx += num_read;
  634.             toread -= num_read;
  635.         }
  636.         if (num_read >= toread) {
  637.             bx += num_read;
  638.             toread -= num_read;
  639.         }
  640.         buffer_end = bx;
  641.         bx = buffer;
  642.         /* buffer_end = buffer + toread; */
  643.  
  644.         while ((buffer=(unsigned char *) getword(word, buffer, buffer_end, &attribute)) < buffer_end) {
  645.             /* printf("%s\n", word); */
  646.             if(word[0] == '\0') continue;
  647.             if(icount - hash_icount >= I_THRESHOLD) {
  648. #if    BG_DEBUG
  649.             fprintf(LOGFILE, "reached I_THRESHOLD at %d\n", icount - hash_icount);
  650. #endif    /*BG_DEBUG*/
  651.             traverse1();
  652.             init_hash_table();
  653.             hash_icount = icount;
  654.             }
  655.             insert_h(word, i, attribute);
  656.         }
  657.         if (word[0] != '\0') {
  658.             /* printf("%s\n", word); */
  659.             if(icount - hash_icount >= I_THRESHOLD) {
  660. #if    BG_DEBUG
  661.             fprintf(LOGFILE, "reached I_THRESHOLD at %d\n", icount - hash_icount);
  662. #endif    /*BG_DEBUG*/
  663.             traverse1();
  664.             init_hash_table();
  665.             hash_icount = icount;
  666.             }
  667.             insert_h(word, i, attribute);
  668.         }
  669.         buffer = bx;
  670.         }
  671.  
  672.     break_break1:
  673.             fclose(fd);
  674.         if (unlinkname != NULL) unlink(unlinkname);
  675.  
  676. #ifdef    UDI_DEBUG
  677.         printf("add to index: %d\n",icount-save_icount);
  678. #endif
  679.         if ((MAXWORDSPERFILE > 0) && (icount-save_icount > MAXWORDSPERFILE)) {
  680.         fprintf(MESSAGEFILE, "%d words are contributed by %s\n",
  681.             icount-save_icount, name_list[i]);
  682.         AddedMaxWordsMessage = ON;
  683.         }
  684.  
  685.         if (IndexNumber && NUMERICWORDPERCENT && (numeric_icount * 100 > (icount - save_icount) * NUMERICWORDPERCENT) && (icount - save_icount > MIN_WORDS)) {
  686.         fprintf(MESSAGEFILE, "NUMBERS occur in %d%% of %d words contributed by %s\n", (numeric_icount * 100)/(icount - save_icount), icount - save_icount, name_list[i]);
  687.         AddedMixedWordsMessage = ON;
  688.         }
  689.  
  690.         numeric_icount=0;
  691.         save_icount=icount;
  692.         if (StructuredIndex) region_destroy();
  693.         }
  694.  
  695.     my_free(bx, BLOCK_SIZE);
  696.     return;
  697.     }
  698.  
  699.     for(pn=1; pn < part_num; pn++)    /* partition # 0 is not accessed */
  700.     {
  701.     if (pn == '\n') continue;    /* There cannot be a partition # '\n' or 0: see partition.c */
  702.     for(i=p_table[pn]; i<p_table[pn+1]; i++) {
  703.         unlinkname = NULL;
  704.         if (disable_list[block2index(i)] & mask_int[i%(8*sizeof(int))]) continue;
  705.         if (BuildDictionaryExisting) {
  706.         if (((fd = fopen(name_list[i], "r")) == NULL) ) {
  707.             fprintf(stderr, "permission denied or non-existent file: %s\n", name_list[i]);
  708.             remove_filename(i, -1);
  709.             continue;
  710.         }
  711.         if (!CompressAfterBuild) unlinkname = name_list[i];    /* not needed anymore */
  712.         goto index_file2;
  713.         }
  714.         if ((ret = tuncompress_file(name_list[i], outname, TC_EASYSEARCH | TC_OVERWRITE | TC_NOPROMPT)) > 0) {    /* do not remove old .TZ file */
  715.         if (((fd = fopen(outname, "r")) == NULL) ) {
  716.             remove_filename(i, -1);
  717.             unlink(outname);
  718.             continue;
  719.         }
  720.         /* not handling structured indices for compressed files now since offset computations will be incorrect */
  721.         if (BuildDictionary && CompressAfterBuild) strcpy(name_list[i], outname);    /* name of clear file will be smaller, so enough space */
  722.         else unlinkname = outname;
  723.         goto index_file2;
  724.         }
  725.  
  726.         /* Try to apply the filter */
  727.         sprintf(outname, "%s/.glimpse_apply.%d", INDEX_DIR, pid);
  728.         if ((ret = apply_filter(name_list[i], outname)) == 1) {
  729.         /* Some pattern matched AND some filter was successful */
  730.         if (((fd = fopen(outname, "r")) == NULL) ) {    /* error: shouldn't have returned 1! */
  731.             remove_filename(i, -1);
  732.             unlink(outname);
  733.             continue;
  734.         }
  735.         /* not handling structured indices for filtered files now since offset computations will be incorrect */
  736.         unlinkname = outname;
  737.         goto index_file2;
  738.         }
  739.         else if (ret == 2) {
  740.         /* Some pattern matched but no filter was successful */
  741.         if (filetype(name_list[i], 0)) {    /* try to index input file if it satisfies filetype */
  742.             remove_filename(i, -1);
  743.             unlink(outname);
  744.             continue;
  745.         }
  746.         unlinkname = outname;
  747.         }
  748.  
  749.         if (StructuredIndex && (-1 == region_create(name_list[i]))) {
  750.         fprintf(stderr, "permission denied or non-existent file: %s\n", name_list[i]);
  751.         remove_filename(i, -1);
  752.         continue;
  753.         }
  754.             if (((fd = fopen(name_list[i], "r")) == NULL) ) {
  755.         fprintf(stderr, "permission denied or non-existent file: %s\n", name_list[i]);
  756.         remove_filename(i, -1);
  757.         if (StructuredIndex) region_destroy();    /* cannot happen! */
  758.         continue;
  759.             }
  760.  
  761.     index_file2:
  762. #ifdef SW_DEBUG
  763.         if (AddToIndex || FastIndex) printf("adding words of %s in %d\n", name_list[i], pn);
  764.         printf("%s\n", name_list[i]);
  765. #endif
  766.         /* stat(name_list[i], &stbuf); Chris Dalton */
  767.         fstat(fileno(fd), &stbuf);
  768. #ifdef    SW_DEBUG
  769.         printf("filesize: %d\n", stbuf.st_size);
  770. #endif
  771.  
  772. #ifdef    UDI_DEBUG
  773.         printf("%s  ", name_list[i]);
  774.         printf("size: %d  ", stbuf.st_size);
  775. #endif
  776.  
  777.         /* buffer always points to a BLOCK_SIZE block of allocated memory */
  778.         for (offset = 0; offset < stbuf.st_size; offset += BLOCK_SIZE) {
  779.         NextICurrentFileOffset = ICurrentFileOffset = offset;
  780.         toread = offset + BLOCK_SIZE >= stbuf.st_size ? stbuf.st_size - offset : BLOCK_SIZE;
  781.         fseek(fd, offset, 0);
  782.  
  783.         bx= buffer;
  784.         num_read = 0;
  785.         while ((toread > 0) && ((num_read = fread(bx, 1, toread, fd)) < toread)) {
  786.             if (num_read <= 0) {
  787.             buffer = bx;
  788.             fprintf(stderr, "read error on file %s at offset %d\n", name_list[i], offset);
  789.             goto break_break2;    /* C doesn't have break; break; */
  790.             }
  791.             bx += num_read;
  792.             toread -= num_read;
  793.         }
  794.         if (num_read >= toread) {
  795.             bx += num_read;
  796.             toread -= num_read;
  797.         }
  798.         buffer_end = bx;
  799.         bx = buffer;
  800.         /* buffer_end = buffer + toread; */
  801.  
  802.         while ((buffer=(unsigned char *) getword(word, buffer, buffer_end, &attribute)) < buffer_end) {
  803.             /* printf("%s\n", word); */
  804.             if(word[0] == '\0') continue;
  805.             if(icount - hash_icount >= I_THRESHOLD) {
  806. #if    BG_DEBUG
  807.             fprintf(LOGFILE, "reached I_THRESHOLD at %d\n", icount - hash_icount);
  808. #endif    /*BG_DEBUG*/
  809.             traverse1();
  810.             init_hash_table();
  811.             hash_icount = icount;
  812.             }
  813.             insert_h(word, pn, attribute);
  814.         }
  815.         if (word[0] != '\0') {
  816.             /* printf("%s\n", word); */
  817.             if(icount - hash_icount >= I_THRESHOLD) {
  818. #if    BG_DEBUG
  819.             fprintf(LOGFILE, "reached I_THRESHOLD at %d\n", icount - hash_icount);
  820. #endif    /*BG_DEBUG*/
  821.             traverse1();
  822.             init_hash_table();
  823.             hash_icount = icount;
  824.             }
  825.             insert_h(word, pn, attribute);
  826.         }
  827.         buffer = bx;
  828.         }
  829.  
  830.     break_break2:
  831.             fclose(fd);
  832.         if (unlinkname != NULL) unlink(unlinkname);
  833.  
  834. #ifdef    UDI_DEBUG
  835.         printf("add to index: %d\n",icount-save_icount);
  836. #endif
  837.         if ((MAXWORDSPERFILE > 0) && (icount-save_icount > MAXWORDSPERFILE)) {
  838.         fprintf(MESSAGEFILE, "%d words are contributed by %s\n",
  839.             icount-save_icount, name_list[i]);
  840.         AddedMaxWordsMessage = ON;
  841.         }
  842.  
  843.         if (IndexNumber && NUMERICWORDPERCENT && (numeric_icount * 100 > (icount - save_icount) * NUMERICWORDPERCENT) && (icount - save_icount > MIN_WORDS)) {
  844.         fprintf(MESSAGEFILE, "NUMBERS occur in %d%% of %d words contributed by %s\n", (numeric_icount * 100)/(icount - save_icount), icount - save_icount, name_list[i]);
  845.         AddedMixedWordsMessage = ON;
  846.         }
  847.  
  848.         numeric_icount=0;
  849.         save_icount=icount;
  850.         if (StructuredIndex) region_destroy();
  851.         }
  852.     }
  853.     my_free(bx, BLOCK_SIZE);
  854. }
  855.  
  856. init_hash_table()
  857. {
  858.     int i;
  859.  
  860.     for(i=0; i<MAX_64K_HASH; i++) hash_table[i] = (struct token *)NULL;
  861.     hash_table[65535] = (struct token *)NULL;
  862.     return;
  863. }
  864.  
  865.  
  866. /* ------------------------------------------------------------------------
  867. input: a word (a string), a hash table (each entry points to a list of
  868.        tokens. (a token is a structure containing 'word' and a pointer
  869.        to a list of indices)).
  870. function: insert the word to appropriate position in the table.
  871.           if the inserted word is already in the data structure, then
  872.           update the list of indices corresponding to that 'word'.
  873.           otherwise create a new token.
  874. ---------------------------------------------------------------------------*/
  875. insert_h(word, pn, attribute)
  876. char *word;
  877. int  pn;
  878. int attribute;
  879. {
  880.     int hash_value=0;
  881.     struct token *tp;
  882.     struct token *tp_bak;
  883.     struct indices *iip;
  884.     int  wordlen = strlen(word);
  885.     int  tried_once;
  886.  
  887.     /* all words with same attribute at same place in hash table */
  888.     hash_value = hash64k(word, wordlen);
  889.     tp_bak = tp = hash_table[hash_value];
  890.     while(tp != NULL) {
  891.         if((strcmp(word, tp->word) == 0) && (tp->attribute == attribute)) {
  892.              insert_index(tp, pn);
  893.              return;
  894.         }
  895.     tp_bak = tp;
  896.         tp = tp->next_t;
  897.     }
  898.  
  899.     /* this is a new word, insert it */
  900.     tried_once = 0;
  901. try_again_2:
  902.     if((tp = (struct token *) my_malloc(sizeof(struct token))) == NULL) {
  903.     tp_bak = NULL;
  904.     fprintf(stderr, "not enough memory in insert_h1 at icount=%d. skipping...\n", icount);
  905.     if (tried_once) return;
  906.     traverse1();
  907.     init_hash_table();
  908.     tried_once = 1;
  909.     goto try_again_2;
  910.     }
  911.  
  912.     tried_once = 0;
  913. try_again_3:
  914.     if((tp->word = (char *) my_malloc(sizeof(char) * (wordlen+1))) == NULL) {
  915.     tp_bak = NULL;
  916.     fprintf(stderr, "not enough memory in insert_h2 at icount=%d. skipping...\n", icount);
  917.     if (tried_once) {
  918.         my_free(tp, sizeof(struct token));
  919.         return;
  920.     }
  921.     traverse1();
  922.     init_hash_table();
  923.     tried_once = 1;
  924.     goto try_again_3;
  925.     }
  926.     strcpy(tp->word, word);
  927.     tp->attribute = attribute;
  928.  
  929.     /* the index list has a first index */
  930.     tried_once = 0;
  931. try_again_4:
  932.     if((iip = (struct indices *) my_malloc(sizeof(struct indices))) == NULL) {
  933.     tp_bak = NULL;
  934.     fprintf(stderr, "not enough memory in insert_h3 at icount=%d. skipping...\n", icount);
  935.     if (tried_once) {
  936.         my_free(tp->word, wordlen + 1);
  937.         my_free(tp, sizeof(struct token));
  938.         return;
  939.     }
  940.     traverse1();
  941.     init_hash_table();
  942.     tried_once = 1;
  943.     goto try_again_4;
  944.     }
  945.     icount++;
  946.  
  947.     if (IndexNumber && NUMERICWORDPERCENT) {
  948.     int    i=0;
  949.     while(word[i] != '\0') {
  950.         if (!isalpha(word[i])) break;
  951.         i++;
  952.     }
  953.     if (word[i] != '\0') numeric_icount ++;
  954.     }
  955.  
  956. #ifdef SW_DEBUG
  957.     if((icount & 01777) == 0) printf("icount = %d\n", icount);
  958. #endif
  959.  
  960.     iip->count = 1;
  961.     if (!CountWords) {
  962.     iip->index[0] = pn;
  963.     iip->offset[0] = ICurrentFileOffset;
  964.     }
  965.  
  966.     /* assign both head and tail */
  967.     iip->next_i = NULL;
  968.     tp->ip = iip;
  969.     tp->lastip = iip;
  970.  
  971.     if(tp_bak == NULL) hash_table[hash_value] = tp;
  972.     else  tp_bak->next_t = tp;
  973.     tp->next_t = NULL;
  974.     tp->totalcount = 1;
  975. }
  976.  
  977. /* -------------------------------------------------------------------
  978. insert_index(): insert an index, i.e., pn, into an indices structure.
  979. The indices structure is a linked list where the 'first' one is always
  980. the active indices structure. When the active one is filled with 8 indices
  981. an indicies structure is created and becomes the active one.
  982. tp points to the token structure. so, tp->ip is always the active
  983. indices structure.
  984. ------------------------------------------------------------------- */
  985. insert_index(tp, pn)
  986. struct token *tp;               /* insert a index into a indices structure */
  987. int pn;
  988. {
  989.     struct indices *iip, *temp;
  990.     struct indices *ip = (ByteLevelIndex ? tp->lastip : tp->ip);
  991.     int tried_once;
  992.  
  993.     if (CountWords) {    /* I am not interested in maintaining where a word occurs: only the number of times it occurs */
  994.     ip->count ++;
  995.     return;
  996.     }
  997.  
  998.     /* Check for stop-list */
  999.     if (OneFilePerBlock && !ByteLevelIndex && (file_num > MaxNum8bPartition) && (tp->totalcount > (file_num * MAX_INDEX_PERCENT / 100))) return;
  1000.     if (ByteLevelIndex && (tp->totalcount > ( (((total_size>>20) > 0) && ((total_size>>20)*MAX_PER_MB < MAX_ALL_INDEX)) ? ((total_size>>20) * MAX_PER_MB) : DEF_ALL_INDEX) )) return;
  1001.  
  1002.     if (ByteLevelIndex) {
  1003.     if ((ip->index[ip->count - 1] == pn) && (ip->offset[ip->count - 1] == ICurrentFileOffset)) return;    /* in identical position */
  1004.     }
  1005.     else if (ip->index[ip->count - 1] == pn) return;    /* current word is not the first appearance in partition pn */
  1006.     if(ip->count < 8) {
  1007.     ip->offset[ip->count] = ICurrentFileOffset;
  1008.         ip->index[ip->count++] = pn;
  1009.         return;
  1010.     }
  1011.  
  1012.     tried_once = 0;
  1013. try_again_5:
  1014.     if((iip = (struct indices *) my_malloc(sizeof(struct indices)))==NULL) {
  1015.     fprintf(stderr, "not enough memory in insert_index at icount=%d. skipping...\n", icount);
  1016.     if (tried_once) return;
  1017.     traverse1();
  1018.     init_hash_table();
  1019.     tried_once = 1;
  1020.     goto try_again_5;
  1021.     }
  1022.     icount++;
  1023.  
  1024.     if (ByteLevelIndex) {
  1025.     /* insert at the end */
  1026.     tp->lastip->next_i = iip;
  1027.     iip->next_i = NULL;
  1028.     tp->lastip = iip;
  1029.     }
  1030.     else {
  1031.     iip->next_i = tp->ip;
  1032.     tp->ip = iip;
  1033.     }
  1034.  
  1035.     iip->count = 1;
  1036.     iip->offset[0] = ICurrentFileOffset;
  1037.     iip->index[0] = pn;
  1038.     tp->totalcount ++;
  1039.     if ( (OneFilePerBlock && !ByteLevelIndex && (file_num > MaxNum8bPartition) && (tp->totalcount > (file_num * MAX_INDEX_PERCENT / 100))) ||
  1040.         (ByteLevelIndex && (tp->totalcount > ( (((total_size>>20) > 0) && ((total_size>>20)*MAX_PER_MB < MAX_ALL_INDEX)) ? ((total_size>>20) * MAX_PER_MB) : DEF_ALL_INDEX) )) ) {
  1041.     for (iip=tp->ip; iip != NULL; temp = iip, iip = iip->next_i, my_free(temp, sizeof(struct indices)));
  1042.     tp->ip = NULL;    /* never need to insert anything else here */
  1043.     }
  1044. /*
  1045. printf("returning from insert_index()\n");
  1046. fflush(stderr);
  1047. */
  1048.     return;
  1049. }
  1050.  
  1051.  
  1052. /* -----------------------------------------------------------------
  1053. input: a word (a string of ascii character terminated by NULL)
  1054. output: a hash_value of the input word.
  1055. hash function: if the word has length <= 4
  1056.         the hash value is just a concatenation of the last four bits
  1057.         of the characters.
  1058.         if the word has length > 4, then after the above operation,
  1059.         the hash value is updated by adding each remaining character.
  1060.         (and AND with the 16-bits mask).
  1061. ---------------------------------------------------------------- */
  1062. hash64k(word, len)
  1063. char *word;
  1064. int len;
  1065. {
  1066.     unsigned int hash_value=0;
  1067.     unsigned int mask_4=017;
  1068.     unsigned int mask_16=0177777;
  1069.     int i;
  1070.  
  1071.     if(len<=4) {
  1072.     for(i=0; i<len; i++) {
  1073.                hash_value = (hash_value << 4) | (word[i]&mask_4);
  1074.         /* hash_value = hash_value  & mask_16; */ 
  1075.     }
  1076.     }
  1077.     else {
  1078.     for(i=0; i<4; i++) {
  1079.                hash_value = (hash_value << 4) | (word[i]&mask_4);
  1080.         /* hash_value = hash_value & mask_16;  */
  1081.     }
  1082.     for(i=4; i<len; i++) 
  1083.         hash_value = mask_16 & (hash_value + word[i]);
  1084.     }
  1085.     return(hash_value & mask_16);
  1086. }
  1087.  
  1088. /* Scan the indexed "word" from an index line: see io.c/merge_splits() */
  1089. scanword(word, buffer, buffer_end)
  1090. unsigned char *word, *buffer, *buffer_end;
  1091. {
  1092.     int i = MAX_WORD_SIZE;
  1093.     if (StructuredIndex) {
  1094.     word[0] = buffer[0];
  1095.     word[1] = buffer[1];
  1096.     word[2] = buffer[2];
  1097.     word[3] = buffer[3];
  1098.     buffer += 4;    /* skip over 4B attribute field */
  1099.     word += 4;
  1100.     }
  1101.     while ((i-- != 0) && (buffer <= buffer_end) && (*buffer != ALL_INDEX_MARK) && (*buffer != WORD_END_MARK) && (*buffer != '\n') && (*buffer != '\0'))
  1102.     *word ++ = *buffer ++;
  1103.     *word = '\0';
  1104. }
  1105.  
  1106. /* Globals used in merge, and also in glimpse's main.c */
  1107. unsigned int src_index_set[REAL_PARTITION];
  1108. unsigned int dest_index_set[REAL_PARTITION];
  1109. unsigned char src_index_buf[REAL_INDEX_BUF];
  1110. unsigned char dest_index_buf[REAL_INDEX_BUF];
  1111. unsigned char merge_index_buf[REAL_INDEX_BUF];
  1112.  
  1113. /* merge index file f1 and f2, then put the result in index file f3 */
  1114. merge_in(f1, f2, f3)
  1115. FILE *f1, *f2, *f3;
  1116. {
  1117.     int src_mark, dest_mark;
  1118.     int    src_num, dest_num;
  1119.     int src_end_pt, dest_end_pt;
  1120.     int cmp=0; /* the result of strcmp */
  1121.     int bdx, bdx1, bdx2, merge_len, i, j;
  1122.     int TAIL1=0;
  1123.     char word1[MAX_WORD_SIZE+6];    /* used only for strcmp() */
  1124.     char word2[MAX_WORD_SIZE+6];    /* used only for strcmp() */
  1125.     int x=0, y=0, even_words = 1;
  1126.  
  1127.     /* LOOK OUT FOR: [memset, fgets, endpt-forloop, scanword] 4-tuples: invariant */
  1128.  
  1129. #if    debug
  1130. printf("in merge_in()\n"); fflush(stdout);
  1131. #endif
  1132.     memset(dest_index_buf, '\0', REAL_INDEX_BUF);
  1133.     fgets(dest_index_buf, REAL_INDEX_BUF, f2);
  1134.     dest_index_buf[REAL_INDEX_BUF - 1] = '\0';
  1135.     dest_end_pt = strlen(dest_index_buf);
  1136.     scanword(word2, dest_index_buf, dest_index_buf+dest_end_pt);
  1137.  
  1138. #ifdef debug
  1139.     printf("word2 = %s\n", word2);
  1140. #endif
  1141.     memset(src_index_buf, '\0', REAL_INDEX_BUF);
  1142.     while(fgets(src_index_buf, REAL_INDEX_BUF, f1)) {
  1143.     src_index_buf[REAL_INDEX_BUF - 1] = '\0';
  1144.     src_end_pt = strlen(src_index_buf);
  1145.         scanword(word1, src_index_buf, src_index_buf+src_end_pt);
  1146.  
  1147. #ifdef debug
  1148.     printf("word1 = %s\n", word1);
  1149. #endif
  1150.     while((cmp = strncmp(word1, word2, MAX_WORD_SIZE+4)) > 0) {
  1151.         fputs(dest_index_buf, f3);
  1152.  
  1153.         memset(dest_index_buf, '\0', dest_end_pt+2);
  1154.         if(fgets(dest_index_buf, REAL_INDEX_BUF, f2) == NULL) {
  1155.         dest_index_buf[REAL_INDEX_BUF - 1] = '\0';
  1156.         TAIL1 = ON;
  1157.         break;
  1158.         }
  1159.         dest_index_buf[REAL_INDEX_BUF - 1] = '\0';
  1160.         dest_end_pt = strlen(dest_index_buf);
  1161.             scanword(word2, dest_index_buf, dest_index_buf+dest_end_pt);
  1162.     }
  1163.         if(TAIL1 == ON) break;
  1164.         if(cmp == 0) { /* we need to join the index of word1 and word2 */
  1165. #ifdef debug
  1166.         printf("joining src_index_buf and dest_index_buf\n");
  1167.         printf("src_index_buf = %s", src_index_buf);
  1168.         printf("dest_index_buf = %s", dest_index_buf);
  1169. #endif
  1170.  
  1171.         if (!CountWords && !ByteLevelIndex) {    /* have to look for common indices and exclude them */
  1172.             int oldbdx1, oldbdx2;
  1173.  
  1174.             merge_index_buf[0] = '\0';
  1175.             merge_len = 0;
  1176.  
  1177.             if (StructuredIndex) oldbdx1 = bdx1 = 4;
  1178.             else oldbdx1 = bdx1 = 0;
  1179.             /* src_index_buf[src_end_pt] is '\0', src_index_buf[src_end_pt-1] is '\n' */
  1180.             while((bdx1 < src_end_pt) && (src_index_buf[bdx1] != WORD_END_MARK) && (src_index_buf[bdx1] != ALL_INDEX_MARK)) bdx1 ++;
  1181.             if ((bdx1 > oldbdx1) && (bdx1 < src_end_pt)) {    /* src_index_buf[bdx1] is the word-end-mark */
  1182.             src_mark = src_index_buf[bdx1];
  1183.             src_index_buf[bdx1] = '\0';    /* terminate word */
  1184.             strcpy(merge_index_buf, src_index_buf);    /* save the word itself */
  1185.             merge_len = strlen(src_index_buf);    /* merge_index_buf[merge_len] is '\0', merge_index_buf[merge_len-1] is a part of the word */
  1186.             bdx1 ++;        /* skip word end marker: src_index_buf[bdx1] is a partition# */
  1187.             }
  1188.  
  1189.             even_words = 1;
  1190.             src_num = 0;
  1191.             if (OneFilePerBlock) memset((char *)src_index_set, '\0', round(file_num, 8)+2);
  1192.             else memset((char *)src_index_set, '\0', sizeof(int) * (MAX_PARTITION + 1));
  1193.             while(bdx1 < src_end_pt - 1) {
  1194.             if (OneFilePerBlock) {
  1195.               x = 0;
  1196.               if (file_num <= MaxNum8bPartition) {
  1197.                 x = decode8b(src_index_buf[bdx1]);
  1198.                 bdx1 ++;
  1199.               }
  1200.               else if (file_num <= MaxNum12bPartition) {
  1201.                 if (even_words) {
  1202.                 x = ((src_index_buf[bdx1+1] & 0x0000000f) << 8) | src_index_buf[bdx1];
  1203.                 x = decode12b(x);
  1204.                 bdx1 += 2;
  1205.                 even_words = 0;
  1206.                 }
  1207.                 else {    /* odd number of words so far */
  1208.                 x = ((src_index_buf[bdx1-1] & 0x000000f0) << 4) | src_index_buf[bdx1];
  1209.                 x = decode12b(x);
  1210.                 bdx1 ++;
  1211.                 even_words = 1;
  1212.                 }
  1213.               }
  1214.               else if (file_num <= MaxNum16bPartition) {
  1215.                 x = (src_index_buf[bdx1] << 8) | src_index_buf[bdx1+1];
  1216.                 x = decode16b(x);
  1217.                 bdx1 += 2;
  1218.               }
  1219.               src_index_set[block2index(x)] |= mask_int[x % (8*sizeof(int))];
  1220.               src_num ++;
  1221.             }
  1222.             else src_index_set[src_num++] = src_index_buf[bdx1++];
  1223.             }
  1224.  
  1225.             if (StructuredIndex) oldbdx2 = bdx2 = 4;
  1226.             else oldbdx2 = bdx2 = 0;
  1227.             /* dest_index_buf[dest_end_pt] is '\0', dest_index_buf[dest_end_pt-1] is '\n' */
  1228.             while((bdx2 < dest_end_pt) && (dest_index_buf[bdx2] != WORD_END_MARK) && (dest_index_buf[bdx2] != ALL_INDEX_MARK)) bdx2 ++;
  1229.             if ((bdx2 > oldbdx2) && (bdx2 < dest_end_pt)) {    /* dest_index_buf[bdx2] is the word-end-mark */
  1230.             dest_mark = dest_index_buf[bdx2];
  1231.             dest_index_buf[bdx2] = '\0';    /* terminate word */
  1232.             if (merge_len == 0) {
  1233.                 strcpy(merge_index_buf, dest_index_buf);    /* save the word itself */
  1234.                 merge_len = strlen(merge_index_buf);
  1235.                 /* merge_index_buf[merge_len] is '\0', merge_index_buf[merge_len-1] is a part of the word */
  1236.             }
  1237.             bdx2 ++;        /* skip word end marker: dest_index_buf[bdx2] is a partition# */
  1238.             }
  1239.  
  1240.             even_words = 1;
  1241.             dest_num = 0;
  1242.             if (OneFilePerBlock) memset((char *)dest_index_set, '\0', round(file_num, 8)+2);
  1243.             else memset((char *)dest_index_set, '\0', sizeof(int) * (MAX_PARTITION + 1));
  1244.             while(bdx2 < dest_end_pt - 1) {
  1245.             if (OneFilePerBlock) {
  1246.               x = 0;
  1247.               if (file_num <= MaxNum8bPartition) {
  1248.                 x = decode8b(dest_index_buf[bdx2]);
  1249.                 bdx2 ++;
  1250.               }
  1251.               else if (file_num <= MaxNum12bPartition) {
  1252.                 if (even_words) {
  1253.                 x = ((dest_index_buf[bdx2+1] & 0x0000000f) << 8) | dest_index_buf[bdx2];
  1254.                 x = decode12b(x);
  1255.                 bdx2 += 2;
  1256.                 even_words = 0;
  1257.                 }
  1258.                 else {    /* odd number of words so far */
  1259.                 x = ((dest_index_buf[bdx2-1] & 0x000000f0) << 4) | dest_index_buf[bdx2];
  1260.                 x = decode12b(x);
  1261.                 bdx2 ++;
  1262.                 even_words = 1;
  1263.                 }
  1264.               }
  1265.               else if (file_num <= MaxNum16bPartition) {
  1266.                 x = (dest_index_buf[bdx2] << 8) | dest_index_buf[bdx2+1];
  1267.                 x = decode16b(x);
  1268.                 bdx2 += 2;
  1269.               }
  1270.               dest_index_set[block2index(x)] |= mask_int[x % (8*sizeof(int))]; 
  1271.               dest_num ++;
  1272.             }
  1273.             else dest_index_set[dest_num++] = dest_index_buf[bdx2++];
  1274.             }
  1275.  
  1276.             even_words = 1;
  1277.             if (merge_len > 0) {
  1278.             if(OneFilePerBlock &&
  1279.                ((src_mark == ALL_INDEX_MARK) ||
  1280.                 (dest_mark == ALL_INDEX_MARK) ||
  1281.                 ((file_num > MaxNum8bPartition) && (src_num + dest_num > file_num*MAX_INDEX_PERCENT / 100)) )) {
  1282.                 merge_index_buf[merge_len++] = ALL_INDEX_MARK;
  1283.                 if (file_num <= MaxNum8bPartition)
  1284.                 merge_index_buf[merge_len ++] = encode8b(DONT_CONFUSE_SORT);
  1285.                 else if (file_num <= MaxNum12bPartition) {
  1286.                 merge_index_buf[merge_len ++] = (encode12b(DONT_CONFUSE_SORT) & 0x00000f00) >> 8;
  1287.                 merge_index_buf[merge_len ++] = encode12b(DONT_CONFUSE_SORT) & 0x000000ff;
  1288.                 }
  1289.                 else {
  1290.                 merge_index_buf[merge_len ++] = (encode16b(DONT_CONFUSE_SORT) & 0x0000ff00) >> 8;
  1291.                 merge_index_buf[merge_len ++] = encode16b(DONT_CONFUSE_SORT) & 0x000000ff;
  1292.                 }
  1293.                 goto final_merge;
  1294.             }
  1295.  
  1296.             merge_index_buf[merge_len++] = WORD_END_MARK;
  1297.             if (OneFilePerBlock) {
  1298.                 for (i=0; i<round(file_num, 8*sizeof(int)); i++) dest_index_set[i] |= src_index_set[i];    /* take union */
  1299.                 for (i=0; i<round(file_num, 8*sizeof(int)); i++)
  1300.                 if (dest_index_set[i])
  1301.                     for (j=0; j<8*sizeof(int); j++)
  1302.                     if (dest_index_set[i] & mask_int[j]) {
  1303.                         x = i*8*sizeof(int) + j;
  1304.                         if (file_num <= MaxNum8bPartition) {
  1305.                             merge_index_buf[merge_len++] = encode8b(x);
  1306.                         }
  1307.                         else if (file_num <= MaxNum12bPartition) {
  1308.                             x = encode12b(x);
  1309.                             if (even_words) {
  1310.                             merge_index_buf[merge_len++] = x & 0x000000ff;    /* lsb */
  1311.                             y = (x & 0x00000f00)>>8;    /* msb */
  1312.                             even_words = 0;
  1313.                             }
  1314.                             else {    /* odd number of words so far */
  1315.                             y |= (x&0x00000f00)>>4; /* msb of x into msb of y */
  1316.                             merge_index_buf[merge_len ++] = y;
  1317.                             merge_index_buf[merge_len ++] = x&0x000000ff;
  1318.                             even_words = 1;
  1319.                             }
  1320.                         }
  1321.                         else if (file_num <= MaxNum16bPartition) {
  1322.                             x = encode16b(x);
  1323.                             merge_index_buf[merge_len ++] = (x&0x0000ff00)>>8;
  1324.                             merge_index_buf[merge_len ++] = x&0x000000ff;
  1325.                         }
  1326.                     }
  1327.                 if (!even_words && (file_num <= MaxNum12bPartition))
  1328.                 merge_index_buf[merge_len ++] = y;
  1329.             }
  1330.             else {    /* normal indexing */
  1331.                 for (i=0; i<src_num; i++) {
  1332.                 merge_index_buf[merge_len++] = src_index_set[i];
  1333.                 }
  1334.                 for (j=0; j<dest_num; j++) {
  1335.                 for (i=0; i<src_num; i++)
  1336.                     if (dest_index_set[j] == src_index_set[i]) break;
  1337.                 if (i>=src_num)     /* did not find match */
  1338.                     merge_index_buf[merge_len++] = dest_index_set[j];
  1339.                 /* Doesn't matter if dest_index_set is int-array (merge_index_buf being char array) since dest_index_set has only a char */
  1340.                 }
  1341.             }
  1342.  
  1343.             final_merge:
  1344.             merge_index_buf[merge_len++] = '\n';
  1345.             merge_index_buf[merge_len] = '\0';
  1346.             fputs(merge_index_buf, f3);
  1347.             /* fprintf(stderr, "%d+%d=%d ", src_end_pt, dest_end_pt, merge_len); */
  1348.             } /* merge_len > 0 */
  1349.         }
  1350.         else if (CountWords) {    /* indices are frequencies, so just merge them: OneFilPerBlock is ignored */
  1351.                     strcpy(merge_index_buf, src_index_buf);
  1352.                     bdx = strlen(merge_index_buf);      /* merge_index_buf[bdx] is '\0', merge_index_buf[bdx-1] is '\n' */
  1353.                     if (bdx > 1) bdx--; /* now merge_index_buf[bdx] is '\n', merge_index_buf[bdx-1] is the last index  */
  1354.                     bdx2 = 0;
  1355.  
  1356.                     /* find the first index */
  1357.                     if (IndexNumber) while(isalnum(dest_index_buf[bdx2])) bdx2 ++;
  1358.                     else while(isalpha(dest_index_buf[bdx2])) bdx2++;
  1359.  
  1360.                     /* to skip over the word-end marker of dest_index_buf (which is a blank) */
  1361.                     if (bdx2 > 0) bdx2 ++;
  1362.  
  1363.                     if (bdx >= 1) {
  1364.                         merge_index_buf[bdx++] = ' ';   /* blank separated fscanf-able list of integers representing counts */
  1365.                     }
  1366.  
  1367.                     /* append the indices of word1 to the buffer */
  1368.                     if (dest_index_buf[bdx2] > 0) {
  1369.                         while(dest_index_buf[bdx2]>0) merge_index_buf[bdx++] = dest_index_buf[bdx2++];  /* '\n' gets copied */
  1370.                         merge_index_buf[bdx] = '\0';
  1371.                     }
  1372.                     /* else, no need to copy anything */
  1373.                     fputs(merge_index_buf, f3);
  1374.         }
  1375.         else {    /* indices are actual occurrences (ByteLevelIndex), so just cat them one after the other, src first since that is i2, the 1st one */
  1376.         /* First put out the attribute and the word */
  1377.         bdx1 = 0;
  1378.         if (StructuredIndex) {
  1379.             putc(src_index_buf[0], f3);
  1380.             putc(src_index_buf[1], f3);
  1381.             putc(src_index_buf[2], f3);
  1382.             putc(src_index_buf[3], f3);
  1383.             bdx1 = 4;
  1384.         }
  1385.         while ((bdx1<src_end_pt) && (src_index_buf[bdx1] != WORD_END_MARK) && (src_index_buf[bdx1] != ALL_INDEX_MARK) && (src_index_buf[bdx1] != '\n') && (src_index_buf[bdx1] != '\0'))
  1386.             putc(src_index_buf[bdx1 ++], f3);
  1387.  
  1388.         /* Now check what end-mark we should put */
  1389.         if ((bdx1 >= src_end_pt) || (src_index_buf[bdx1] == ALL_INDEX_MARK) || (src_end_pt + dest_end_pt >= MAX_SORTLINE_LEN)) {
  1390.             putc(ALL_INDEX_MARK, f3);
  1391.             putc(DONT_CONFUSE_SORT, f3);
  1392.             putc('\n', f3);
  1393.         }
  1394.         else {    /* dest can be all index mark */
  1395.             if (StructuredIndex) bdx2 = 4;
  1396.             else bdx2 = 0;
  1397.             while ((bdx2<dest_end_pt) && (dest_index_buf[bdx2] != WORD_END_MARK) && (dest_index_buf[bdx2] != ALL_INDEX_MARK) && (dest_index_buf[bdx2] != '\n') && (dest_index_buf[bdx2] != '\0')) bdx2 ++;
  1398.             if ((bdx2 >= dest_end_pt) || (dest_index_buf[bdx2] == ALL_INDEX_MARK)) {
  1399.             putc(ALL_INDEX_MARK, f3);
  1400.             putc(DONT_CONFUSE_SORT, f3);
  1401.             putc('\n', f3);
  1402.             }
  1403.             else {    /* we have to put out both the lists */
  1404.             putc(WORD_END_MARK, f3);
  1405.             bdx1 ++;    /* skip over WORD_END_MARK */
  1406.             while ((bdx1 < src_end_pt) && (src_index_buf[bdx1] != '\n') && (src_index_buf[bdx1] != '\0')) putc(src_index_buf[bdx1++], f3);
  1407.             fputc(encode8b(0), f3);    /* instead of the '\n' after end of src_index_buf */
  1408.             bdx2 ++;    /* skip over WORD_END_MARK */
  1409.             while ((bdx2 < dest_end_pt) && (dest_index_buf[bdx2] != '\n') && (dest_index_buf[bdx2] != '\0')) putc(dest_index_buf[bdx2++], f3);
  1410.             putc('\n', f3);
  1411.             }
  1412.         }
  1413.         }
  1414. #if debug
  1415.         printf("merge_index_buf = %s", merge_index_buf);
  1416. #endif /*debug*/
  1417.         memset(dest_index_buf, '\0', dest_end_pt+2);
  1418.          if(fgets(dest_index_buf, REAL_INDEX_BUF, f2) == 0)  {
  1419.         dest_index_buf[REAL_INDEX_BUF - 1] = '\0';
  1420.         TAIL1 = ON;
  1421.         break;
  1422.         }
  1423.         dest_index_buf[REAL_INDEX_BUF - 1] = '\0';
  1424.         dest_end_pt = strlen(dest_index_buf);
  1425.             scanword(word2, dest_index_buf, dest_index_buf+dest_end_pt);
  1426.         }
  1427.         else { /* word1 < word2, so output src_index_buf */
  1428.             fputs(src_index_buf, f3);
  1429.         }
  1430.     memset(src_index_buf, '\0', src_end_pt+2);
  1431.     }
  1432.     if(TAIL1) {
  1433.         if(cmp != 0) fputs(src_index_buf, f3);
  1434.     memset(src_index_buf, '\0', src_end_pt+2);
  1435.         while(fgets(src_index_buf, REAL_INDEX_BUF, f1)) {
  1436.         src_index_buf[REAL_INDEX_BUF - 1] = '\0';
  1437.         src_end_pt = strlen(src_index_buf);
  1438.             fputs(src_index_buf, f3);
  1439.         memset(src_index_buf, '\0', src_end_pt+2);
  1440.         }
  1441.     }
  1442.     else { /* output the tail of f2 */
  1443.         fputs(dest_index_buf, f3); 
  1444.     memset(dest_index_buf, '\0', dest_end_pt+2);
  1445.         while(fgets(dest_index_buf, REAL_INDEX_BUF, f2)) {
  1446.         dest_index_buf[REAL_INDEX_BUF - 1] = '\0';
  1447.         dest_end_pt = strlen(dest_index_buf);
  1448.             fputs(dest_index_buf, f3);
  1449.         memset(dest_index_buf, '\0', dest_end_pt+2);
  1450.         }
  1451.     }
  1452.     return;
  1453. }
  1454.  
  1455.  
  1456. remove_filename(fileindex, new_partition)
  1457.     int    fileindex, new_partition;
  1458. {
  1459.     if ((fileindex < 0) || (fileindex >= MAXNUM_FILE)) return;
  1460. #if    BG_DEBUG
  1461.     fprintf(LOGFILE, "removing %s from index\n", name_list[fileindex]);
  1462.     memory_usage -= (strlen(name_list[fileindex]) + 2);
  1463. #endif    /*BG_DEBUG*/
  1464.     my_free(name_list[fileindex], 0);
  1465.     name_list[fileindex] = NULL;
  1466.     disable_list[block2index(fileindex)] |= mask_int[fileindex % (8*sizeof(int))];
  1467. }
  1468.  
  1469.